﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using Pixysoft.Framework.Reflection.Core;
using Pixysoft.Framework.Reflection.Controller;
using Pixysoft.TestDrivens;

namespace Pixysoft.Framework.Reflection.testdriven
{
    [TestDriven]
    class Class_dummy
    {
        interface IAA
        {
            string Name1 { get;}
        }

        interface IBB : IAA
        {
            string Name2 { get;}
        }

        interface ICC : IBB
        {
            string Name3 { get;}
        }

        public void test001()
        {
            foreach (Type type in typeof(ICC).GetInterfaces())
            {
                Console.WriteLine(type.Name);
            }

            Class_dummy[] ss = new Class_dummy[] { };
            List<Class_dummy> list = new List<Class_dummy>();

            Console.WriteLine(ss.GetType().FullName);
            Console.WriteLine(list.GetType().GetGenericTypeDefinition().FullName);
            Console.WriteLine(list.GetType().FullName);
            Console.WriteLine(StringHelper.GetListFullName(list.GetType()));
        }

        // get attribute data
        public void test003()
        {
            foreach (CustomAttributeData attributeData in CustomAttributeData.GetCustomAttributes(typeof(ObjectWithValueAndAttribute)))
            {
                Console.WriteLine(attributeData.GetHashCode());
            }
            foreach (CustomAttributeData attributeData in CustomAttributeData.GetCustomAttributes(typeof(ObjectWithValueAndAttribute)))
            {
                Console.WriteLine(attributeData.Constructor.GetHashCode());
            }
            foreach (CustomAttributeData attributeData in CustomAttributeData.GetCustomAttributes(typeof(ObjectWithValueAndAttribute)))
            {
                Console.WriteLine(attributeData.Constructor.MetadataToken);
            }
        }

        //test value
        [TestCase]
        public static void test004()
        {
            object value = "hello";
            IDummyType type = DummyTypeHandlerFactory.CreateDummyTypeHandler(value.GetType())();
            foreach (IDummyPropertyInfo info in type.GetProperties())
            {
                Console.WriteLine(info.Name);
            }
            Assert.SaveOrVerify("test value string", type);


            value = 123.123;
            type = DummyTypeHandlerFactory.CreateDummyTypeHandler(value.GetType())();
            foreach (IDummyPropertyInfo info in type.GetProperties())
            {
                Console.WriteLine(info.Name);
            }
            Assert.SaveOrVerify("test value double", type);


            value = new byte[] { 0, 1, 2 };
            type = DummyTypeHandlerFactory.CreateDummyTypeHandler(value.GetType())();
            foreach (IDummyPropertyInfo info in type.GetProperties())
            {
                Console.WriteLine(info.Name);
            }
            Assert.SaveOrVerify("test value byte[]", type);




            value = PersonType.B;
            type = DummyTypeHandlerFactory.CreateDummyTypeHandler(value.GetType())();
            foreach (IDummyPropertyInfo info in type.GetProperties())
            {
                Console.WriteLine(info.Name);
            }
            Assert.SaveOrVerify("test value enum", type);




            value = "hello";
            type = DummyTypeHandlerFactory.CreateDummyTypeHandler(value.GetType())();
            foreach (IDummyPropertyInfo info in type.GetProperties())
            {
                Console.WriteLine(info.Name);
            }
            Assert.SaveOrVerify("test value structure string", type);



            value = 123.123;
            type = DummyTypeHandlerFactory.CreateDummyTypeHandler(value.GetType())();
            foreach (IDummyPropertyInfo info in type.GetProperties())
            {
                Console.WriteLine(info.Name);
            }
            Assert.SaveOrVerify("test value structure double", type);



            value = new byte[] { 0, 1, 2 };
            type = DummyTypeHandlerFactory.CreateDummyTypeHandler(value.GetType())();
            foreach (IDummyPropertyInfo info in type.GetProperties())
            {
                Console.WriteLine(info.Name);
            }
            Assert.SaveOrVerify("test value structure byte[]", type);



            value = PersonType.B;
            type = DummyTypeHandlerFactory.CreateDummyTypeHandler(value.GetType())();
            foreach (IDummyPropertyInfo info in type.GetProperties())
            {
                Console.WriteLine(info.Name);
            }
            Assert.SaveOrVerify("test value structure enum", type);
        }

        //test object
        [TestCase]
        public static void test005()
        {
            ObjectWithValueAndAttribute p = new ObjectWithValueAndAttribute();
            p.Age = 1;
            p.Name = "123";
            p.Price = 12;
            p.Type = PersonType.A;

            IDummyType type = DummyTypeHandlerFactory.CreateDummyTypeHandler(p.GetType())();
            Assert.SaveOrVerify("structure serialize", type);
        }


        //test collection
        [TestCase]
        public static void test006()
        {
            ObjectWithValueAndAttribute p = new ObjectWithValueAndAttribute();
            p.Age = 1;
            p.Name = "123";
            p.Price = 12;
            p.Type = PersonType.A;
            ObjectWithValueAndAttribute[] ps = new ObjectWithValueAndAttribute[] { p };
            IDummyType type = DummyTypeHandlerFactory.CreateDummyTypeHandler(ps.GetType())();
            Assert.SaveOrVerify("object collection serialize", type);
            //Assert.SaveOrVerify("object collection serialize property.", (type.Value as IDummyType[])[0].GetProperties());

            type = DummyTypeHandlerFactory.CreateDummyTypeHandler(ps.GetType())();
            Assert.SaveOrVerify("object collection structure serialize.", type);
            Assert.SaveOrVerify("object collection structure serialize elementType.", type.GetElementType());
        }

        //test interface
        [TestCase]
        public static void test007()
        {
            Ivalueinterface p = new ObjectWithValueAndAttribute();
            p.Age = 1;
            p.Name = "123";
            p.Price = 12;
            p.Type = PersonType.A;
            IDummyType type = DummyTypeHandlerFactory.CreateDummyTypeHandler(p.GetType())();
            Assert.SaveOrVerify("dynamic structure serialize interface", p);

            p = Pixysoft.Tools.PojoHelper.GetPojo<Ivalueinterface>();
            p.Age = 1;
            p.Name = "123";
            p.Price = 12;
            p.Type = PersonType.A;
            type = DummyTypeHandlerFactory.CreateDummyTypeHandler(p.GetType())();
            Assert.SaveOrVerify("dynamic structure serialize realproxy pojo", p);
        }

        //test object.interface
        [TestCase]
        public static void test008()
        {
            Ivalueinterface p = new ObjectWithValueAndAttribute();
            p.Age = 1;
            p.Name = "123";
            p.Price = 12;
            p.Type = PersonType.A;

            ObjectWithAll p2 = new ObjectWithAll();
            p2.Age = 1;
            p2.Name = "123";
            p2.Price = 12;
            p2.Type = PersonType.A;
            p2.Child = p;



            IDummyType type = DummyTypeHandlerFactory.CreateDummyTypeHandler(p2.GetType())();
            Assert.SaveOrVerify("dynamic structure serialize object_interface", type);
            Assert.SaveOrVerify("dynamic structure serialize object_interface.property", (type as IDummyType).GetProperty("Child"));
        }

        //valuelist
        [TestCase]
        public static void test009()
        {
            List<string> papers = new List<string>();
            papers.Add("hwer");
            IDummyType type = DummyTypeHandlerFactory.CreateDummyTypeHandler(papers.GetType())();
            Assert.SaveOrVerify("structure serialize valuelist", type);
        }

        //object.object
        [TestCase]
        public static void test012()
        {
            ObjectWithValueAndAttribute p = new ObjectWithValueAndAttribute();
            p.Age = 1;
            p.Name = "123";
            p.Price = 12;
            p.Type = PersonType.A;

            ObjectWithAll p2 = new ObjectWithAll();
            p2.Age = 1;
            p2.Name = "123";
            p2.Price = 12;
            p2.Type = PersonType.A;
            p2.Pp = p;

            IDummyType type = DummyTypeHandlerFactory.CreateDummyTypeHandler(p2.GetType())();
            Assert.SaveOrVerify("structure serialize object.object", type);
        }

        //object.binary
        [TestCase]
        public static void test013()
        {
            ReflectionManager.OutputToConsole = true;
            ObjectWithAll p2 = new ObjectWithAll();
            p2.Age = 1;
            p2.Name = "123";
            p2.Price = 12;
            p2.Type = PersonType.A;
            p2.Image = new byte[] { 0, 1 };

            IDummyType type2 = DummyTypeHandlerFactory.CreateDummyTypeHandler(p2.GetType())();

            Assert.SaveOrVerify("structure serialize object.binary", type2);
        }

        //object.valuearray
        [TestCase]
        public static void test014()
        {
            ObjectWithAll p2 = new ObjectWithAll();
            p2.Age = 1;
            p2.Name = "123";
            p2.Price = 12;
            p2.Type = PersonType.A;
            p2.Hells = new string[] { "213", "321" };
            IDummyType type = DummyTypeHandlerFactory.CreateDummyTypeHandler(p2.GetType())();
            Assert.SaveOrVerify("structure serialize object.valuearray", type);
        }

        //object.objectlist
        [TestCase]
        public static void test015()
        {
            ObjectWithValueAndAttribute p = new ObjectWithValueAndAttribute();
            p.Age = 1;
            p.Name = "123";
            p.Price = 12;
            p.Type = PersonType.A;

            ObjectWithAll p2 = new ObjectWithAll();
            p2.Age = 1;
            p2.Name = "123";
            p2.Price = 12;
            p2.Type = PersonType.A;
            p2.Pss.Add(p);
            p2.Pss.Add(p);

            IDummyType type = DummyTypeHandlerFactory.CreateDummyTypeHandler(p2.GetType())();
            Assert.SaveOrVerify("structure serialize.objectlist", type);
        }

        //object attribute
        [TestCase]
        public static void test016()
        {
            ObjectWithValueAndAttribute p = new ObjectWithValueAndAttribute();
            p.Age = 1;
            p.Name = "123";
            p.Price = 12;
            p.Type = PersonType.A;
            p.Now = DateTime.Now;

            IDummyType type = DummyTypeHandlerFactory.CreateDummyTypeHandler(p.GetType())();
            object oo = type.GetCustomAttributes()[1];
            Assert.SaveOrVerify("structure serialize object.attribute", (oo as SomeAttribute).Id);
        }

        //object:interface[] 继承
        [TestCase]
        public static void test017()
        {
            ObjectWithValueAndAttribute p = new ObjectWithValueAndAttribute();
            p.Age = 1;
            p.Name = "123";
            p.Price = 12;
            p.Type = PersonType.A;
            //p.Now = DateTime.Now;

            IDummyType type = DummyTypeHandlerFactory.CreateDummyTypeHandler(p.GetType())();
            Assert.SaveOrVerify("structure serialize object.interface", type);
        }

        //structure
        [TestCase]
        public static void test018()
        {
            IDummyType type = DummyTypeHandlerFactory.CreateDummyTypeHandler(typeof(ObjectWithAll))();
            Assert.SaveOrVerify("structure serialize structurewithAll", type);
        }

        //method void
        [TestCase]
        public static void test019()
        {
            IDummyType type = DummyTypeHandlerFactory.CreateDummyTypeHandler(typeof(ObjectWithVoidMethod))();
            Assert.SaveOrVerify("structure serialize structure.voidmethod", type.GetMethod("PublicVoidMethod", new IDummyType[] { }));
        }

        //method return
        [TestCase]
        public static void test020()
        {
            IDummyType type = DummyTypeHandlerFactory.CreateDummyTypeHandler(typeof(ObjectWithReturnMethod))();
            Assert.SaveOrVerify("structure serialize structure.methods", type.GetMethods());
        }

        //method parameter
        [TestCase]
        public static void test021()
        {
            IDummyType type = DummyTypeHandlerFactory.CreateDummyTypeHandler(typeof(ObjectWithParameterMethod))();
            Assert.SaveOrVerify("structure serialize structure.methods.withparameter", type.GetMethods()[0].GetParameters());
        }

        //method property
        [TestCase]
        public static void test022()
        {
            IDummyType type = DummyTypeHandlerFactory.CreateDummyTypeHandler(typeof(ObjectWithProperty))();
            Assert.SaveOrVerify("structure serialize structure.propertymethod", type.GetMethods());
        }

    }

    class ObjectWithProperty
    {
        public string Name
        {
            get { return null; }
            set { }
        }
    }

    class ObjectWithParameterMethod
    {
        public void Method(PersonType enump, int valuep, string stringp, byte[] binaryp,
            Ivalueinterface interfacep, ObjectWithAll objectp,
            Ivalueinterface[] interfacearrayp, List<ObjectWithAll> objectlistp)
        {
        }
    }

    class ObjectWithReturnMethod
    {
        public string MethodReturnString()
        {
            throw new Exception();
        }

        public int MethodReturnValue()
        {
            throw new Exception();
        }

        public PersonType MethodReturnEnum()
        {
            throw new Exception();
        }

        public ObjectWithAll MethodReturnObject()
        {
            return null;
        }

        public byte[] MethodReturnBinary()
        {
            return null;
        }

        public ObjectWithAll[] MethodReturnObjectArray() { throw new Exception(); }


        public List<Ivalueinterface> MethodReturnInterfaceList() { throw new Exception(); }
    }

    class ObjectWithVoidMethod
    {
        private void PrivateVoidMethod()
        {
        }
        public void PublicVoidMethod()
        {
        }
        protected void ProtectedVoidMethod()
        {
        }
        protected virtual void ProtectedVirtualVoidMethod()
        {
        }

        public static void PublicStaticVoidMethod()
        {
        }

    }

    interface Ivalueinterface : Ibaseinterface
    {
        int Age { get;set;}
        string Name { get;set;}
        double Price { get;set;}
        PersonType Type { get;set;}
    }

    interface Ibaseinterface
    {
    }

    class ObjectWithAll : Ivalueinterface, Ibaseinterface
    {
        int age;
        string name;
        double price;
        PersonType type;
        Ivalueinterface child;
        ObjectWithValueAndAttribute pp;
        ObjectWithAll pp2;
        List<string> pagers = new List<string>();
        byte[] image;
        string[] hells;
        List<ObjectWithValueAndAttribute> pss = new List<ObjectWithValueAndAttribute>();
        public int Age
        {
            get { return age; }
            set { age = value; }
        }
        public string Name
        {
            get { return name; }
            set { name = value; }
        }
        public double Price
        {
            get { return price; }
            set { price = value; }
        }
        public PersonType Type
        {
            get { return type; }
            set { type = value; }
        }
        public Ivalueinterface Child
        {
            get { return child; }
            set { child = value; }
        }
        public ObjectWithValueAndAttribute Pp
        {
            get { return pp; }
            set { pp = value; }
        }

        public List<string> Pagers
        {
            get { return pagers; }
            set { pagers = value; }
        }
        public byte[] Image
        {
            get { return image; }
            set { image = value; }
        }
        public string[] Hells
        {
            get { return hells; }
            set { hells = value; }
        }
        public List<ObjectWithValueAndAttribute> Pss
        {
            get { return pss; }
            set { pss = value; }
        }
        public ObjectWithAll Pp2
        {
            get { return pp2; }
            set { pp2 = value; }
        }



    }

    [Some("123")]
    [Some(null, "123", -256, 0, true, 1, long.MaxValue, char.MaxValue, PersonType.B)]
    class ObjectWithValueAndAttribute : Ivalueinterface, Ibaseinterface
    {
        int age;
        string name;
        double price;
        PersonType type;
        DateTime now;
        //[Some("123")]
        public int Age
        {
            get { return age; }
            set { age = value; }
        }
        public string Name
        {
            get { return name; }
            set { name = value; }
        }
        public double Price
        {
            get { return price; }
            set { price = value; }
        }
        public PersonType Type
        {
            get { return type; }
            set { type = value; }
        }
        public DateTime Now
        {
            get { return now; }
            set { now = value; }
        }


    }

    enum PersonType
    {
        A = 2, B = 4,
    }

    [AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
    class SomeAttribute : Attribute
    {
        string name;
        string id;
        public SomeAttribute()
        {
        }
        public SomeAttribute(string name)
        {
            this.name = name;
        }
        public SomeAttribute(string name, string id, int intvalue, double doubelvalue, bool boovalue, float floatvalue, Int64 int64value, char charvalue, PersonType enumvalue)
        {
            this.name = name;
            this.id = id;
        }
        public string Name
        {
            get { return name; }
            set { name = value; }
        }
        public string Id
        {
            get { return id; }
            set { id = value; }
        }
    }
}


